/*
 * WllInterpreter.cpp
 *
 *  Created on: 2015-12-31
 *      Author: wll
 */


#include "WllConfigure.h"
#include "WllTrace.h"
#include <fstream>
#include "CompilerManager.h"
#include "Wll0Interpreter.h"
#include "Wll1Interpreter.h"
#include "Wll2Interpreter.h"
#include "Wll3Interpreter.h"
#include "LR1Parsers.h"
#include "TopDownParsers.h"
#include "WllInterpreter.h"
#include <cassert>
#include "WllSingleton.h"

WllInterpreter::WllInterpreter(Compiler* compiler)
{
    this->compiler = compiler;
    if (compiler != nullptr)
    {
        assert(compiler->interpreter == nullptr);
        compiler->interpreter = this;
    }
}

bool WllInterpreter::Interpret(const std::vector<Symbols> &input_symbols, std::vector<Symbols> &output_symbols, Compiler *compiler)
{
    assert(!input_symbols.empty());
    WllInterpreter* interpreter = GetOrCreateWllInterpreter(input_symbols[0], compiler);
    if (interpreter == nullptr)
    {
        INFO("CAN NOT guess wll interpreter version by input_symbols[0] : " << input_symbols[0]);
        CompilerManager* compiler_manager = Singleton<CompilerManager>::GetInstance();
        interpreter = compiler_manager->GetOrCreateWllInterpreter(compiler);
        INFO("create wll interpreter by compiler manager config/wll.cfg");
    }
    INFO("wll interpreter version = " << interpreter->GetVersion());

    return interpreter->InterpretWllVersion(input_symbols, output_symbols);
}

WllInterpreter *WllInterpreter::CreateWllInterpreter(const Symbols& wll_version, Compiler* compiler)
{
    WllInterpreter* interpreter = nullptr;

    if (compiler == nullptr)
    {
        if (wll_version == Symbols::WLL1)
        {
            interpreter = Wll1Interpreter::GetDefaultWll1Interpreter();
        }
        else if (wll_version == Symbols::WLL2)
        {
            interpreter = Wll2Interpreter::GetDefaultWll2Interpreter();
        }
        else if (wll_version == Symbols::WLL3)
        {
            interpreter = Wll3Interpreter::GetDefaultWll3Interpreter();
        }
    }
    else
    {
        if (wll_version == Symbols::WLL1)
        {
            interpreter = new Wll1Interpreter(compiler);
        }
        else if (wll_version == Symbols::WLL2)
        {
            interpreter = new Wll2Interpreter(compiler);
        }
        else if (wll_version == Symbols::WLL3)
        {
            interpreter = new Wll3Interpreter(compiler);
        }
    }

    return interpreter;
}

WllInterpreter *WllInterpreter::GetOrCreateWllInterpreter(const Symbols& wll_version, Compiler* compiler)
{
    if (compiler != nullptr && compiler->interpreter != nullptr) {
        return compiler->interpreter;
    }
    return CreateWllInterpreter(wll_version, compiler);
}